﻿using System;
using System.Linq;
using Sinacor.Infra.UI.Common;
using System.Collections.ObjectModel;
using Sinacor.UI.Bovespa.ManutencaoOrdens.Model;
using Sinacor.Infra.UI.Authorization;
using Sinacor.UI.Bovespa.ManutencaoOrdens;
using Sinacor.Infra.Common.Exceptions;
using System.Collections.Generic;

namespace Sinacor.UI.Bovespa.ManutencaoOrdens.Presenter
{
    /// <summary>
    /// Controla requisições da tela com o negocio
    /// </summary>
    public class ManutencaoOrdens : BasePresenter<IManutencaoOrdens>
    {
        #region Atributos

        private ModelCollection<Model.Bolsa> _bolsas;
        private ModelCollection<Model.Calendario> _calendarioFiltro;
        private Model.Cliente _clienteAtual;
        private Communication.Calendario _communicationCalendario;
        private Communication.Justificativa _communicationJustificativa;
        private Communication.ManutencaoOrdens _communicationManutencaoOrdens;
        private Communication.Negocio _communicationNegocio;
        private Communication.Operador _communicationOperador;
        private Communication.Parametro _communicationParametro;
        private Communication.Titulo _communicationTitulo;
        private Communication.Mensagem _communicationMensagem;
        private Communication.ControleMovimentoOrdens _communicationControleMovimentoOrdens;
        private Communication.Cliente _communicationCliente;
        private ModelCollection<Model.Emissor> _emissores;
        private Model.Enum.EstadoTela _estado;
        private Model.Parameter.FiltroOrdem _filtroOrdens;
        private Model.InformacoesMovimento _informacoesMovimento;
        private ObservableCollection<EnumWrapper<Model.Enum.NaturezaOperacao>> _listaNaturezaOperacao;
        private ModelCollection<Model.Mensagem> _mensagensJustificativas;
        private ModelCollection<Model.Mensagem> _mensagensObservacoes;
        private Model.Enum.ModoTela _modoUtilizado;
        private ModelCollection<Model.Operador> _operadoresSubordinados;
        private Model.Ordem _ordemAtual;
        private ModelCollection<Model.Ordem> _ordensAtuais;
        private ModelCollection<Model.Ordem> _ordens;
        private Model.Parametro _parametros;
        public Model.Permissoes _permissoes;
        private Model.Preferencias _preferencias;
        private Model.QuantidadeNegocioSumarizada _quantidadeSumarizada;
        private ObservableCollection<EnumWrapper<Model.Enum.TipoMercado>> _tiposMercados;
        private ObservableCollection<EnumWrapper<Model.Enum.TipoMercado>> _tiposMercadosDetalhes;
        private ObservableCollection<EnumWrapper<Model.Enum.TipoOrdem>> _tiposOrdens;
        private ObservableCollection<EnumWrapper<Model.Enum.SituacaoOrdem>> _tiposSituacao;
        private ObservableCollection<EnumWrapper<Model.Enum.TipoLiquidacao>> _tiposLiquidacao;
        private ModelCollection<Model.Justificativa> _justificativasHistorico;
        private ModelCollection<Model.Justificativa> _justificativasRecente;
        private Model.Titulo _tituloAtual;
        private bool _habilitaInclusaoOrdem;
        private Dictionary<string, bool> _dicionarioValidadorPropriedadesOrdem = null;

        #endregion

        #region Propriedades
        
        public Dictionary<string, bool> DicionarioValidadorPropriedadesOrdem
        {
            get { return _dicionarioValidadorPropriedadesOrdem; }
            set { _dicionarioValidadorPropriedadesOrdem = value; }
        }

        /// <summary>
        /// 
        /// </summary>
        public ObservableCollection<EnumWrapper<Model.Enum.NaturezaOperacao>> ListaNaturezaOperacao
        {
            get
            {
                return _listaNaturezaOperacao;
            }
            set
            {
                _listaNaturezaOperacao = value;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public ObservableCollection<EnumWrapper<Model.Enum.NaturezaOperacao>> ListaNaturezaOperacaoDetalhe
        {
            get;
            set;
        }

        /// <summary>
        /// 
        /// </summary>
        public ModelCollection<Model.Bolsa> Bolsas
        {
            get
            {
                return _bolsas;
            }
            set
            {
                _bolsas = value;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public ModelCollection<Model.Calendario> CalendarioFiltro
        {
            get
            {
                return _calendarioFiltro;
            }
            set
            {
                _calendarioFiltro = value;
            }
        }

        /// <summary>
        /// Binding com o campo Nome
        /// </summary>
        public Model.Cliente ClienteAtual
        {
            get
            {
                return _clienteAtual;
            }
            set
            {
                _clienteAtual = value;
            }
        }

        /// <summary>
        /// Binding com o combobox de emissores
        /// </summary>
        public ModelCollection<Model.Emissor> Emissores
        {
            get
            {
                return _emissores;
            }
            set
            {
                _emissores = value;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public Model.Enum.EstadoTela Estado
        {
            get
            {
                return _estado;
            }
            set
            {
                _estado = value;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public Model.Parameter.FiltroOrdem FiltroOrdens
        {
            get
            {
                return _filtroOrdens;
            }
            set
            {
                _filtroOrdens = value;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public Model.InformacoesMovimento InformacoesMovimento
        {
            get
            {
                return _informacoesMovimento;
            }
            set
            {
                _informacoesMovimento = value;
            }
        }

        /// <summary>
        /// Binding com o combobox de justificativas padrões
        /// </summary>
        public ModelCollection<Model.Mensagem> MensagensJustificativas
        {
            get
            {
                return _mensagensJustificativas;
            }
            set
            {
                _mensagensJustificativas = value;
            }
        }

        /// <summary>
        /// Binding com o combobox de observacoes padrões
        /// </summary>
        public ModelCollection<Model.Mensagem> MensagensObservacoes
        {
            get
            {
                return _mensagensObservacoes;
            }
            set
            {
                _mensagensObservacoes = value;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public Model.Enum.ModoTela ModoUtilizado
        {
            get
            {
                return _modoUtilizado;
            }
            set
            {
                _modoUtilizado = value;
            }
        }

        /// <summary>
        /// Binding com o combobox de Operador da aba "Pesquisa"
        /// </summary>
        public ModelCollection<Model.Operador> OperadoresSubordinados
        {
            get
            {
                return _operadoresSubordinados;
            }
            set
            {
                _operadoresSubordinados = value;
            }
        }

        /// <summary>
        /// Binding com o combobox de Operador no DataGrid de ordens
        /// </summary>
        public ModelCollection<Model.Operador> OperadoresSubordinadosGrid
        {
            get;
            set;
        }

        /// <summary>
        /// Armazenar a ordem que está selecionada no datagrid da aba Ordens.
        /// </summary>
        public Model.Ordem OrdemAtual
        {
            get
            {
                return _ordemAtual;
            }
            set
            {
                _ordemAtual = value;
            }
        }

        /// <summary>
        /// Armazenar a ordem que está selecionada no datagrid da aba Ordens.
        /// </summary>
        public ModelCollection<Model.Ordem> OrdensAtuais
        {
            get
            {
                return _ordensAtuais;
            }
            set
            {
                _ordensAtuais = value;
            }
        }

        /// <summary>
        /// Binding com a Grid de Ordens (Aba Ordens)
        /// </summary>
        public ModelCollection<Model.Ordem> Ordens
        {
            get
            {
                return _ordens;
            }
            set
            {
                _ordens = value;
                if (_ordens != null)
                    this.Ordens.EnableStateControl = true;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public Model.Parametro Parametros
        {
            get
            {
                return _parametros;
            }
            set
            {
                _parametros = value;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public Model.Permissoes Permissoes
        {
            get
            {
                return _permissoes;
            }
            set
            {
                _permissoes = value;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public Model.Preferencias Preferencias
        {
            get
            {
                return _preferencias;
            }
            set
            {
                _preferencias = value;
            }
        }

        /// <summary>
        /// Realizar binding com os campos Total Compra e Total Venda da aba
        /// Financimanto/POP
        /// </summary>
        public Model.QuantidadeNegocioSumarizada QuantidadeSumarizada
        {
            get
            {
                return _quantidadeSumarizada;
            }
            set
            {
                _quantidadeSumarizada = value;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public ObservableCollection<EnumWrapper<Model.Enum.TipoMercado>> TiposMercados
        {
            get
            {
                return _tiposMercados;
            }
            set
            {
                _tiposMercados = value;
            }
        }

        /// <summary>
        /// Binding com o combobox de Mercado do grid de detalhes (aba Financiamento/POP)
        /// </summary>
        public ObservableCollection<EnumWrapper<Model.Enum.TipoMercado>> TiposMercadosDetalhes
        {
            get
            {
                return _tiposMercadosDetalhes;
            }
            set
            {
                _tiposMercadosDetalhes = value;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public ObservableCollection<EnumWrapper<Model.Enum.TipoOrdem>> TiposOrdens
        {
            get
            {
                return _tiposOrdens;
            }
            set
            {
                _tiposOrdens = value;
            }
        }

        public ObservableCollection<EnumWrapper<Model.Enum.SituacaoOrdem>> TiposSituacao
        {
            get
            {
                return _tiposSituacao;
            }
            set
            {
                _tiposSituacao = value;
            }
        }

        public ObservableCollection<EnumWrapper<Model.Enum.TipoLiquidacao>> TiposLiquidacao
        {
            get
            {
                return _tiposLiquidacao;
            }
            set
            {
                _tiposLiquidacao = value;
            }
        }

        /// <summary>
        /// Binding com o campo descrição da grid e do modo formulário
        /// </summary>
        public Model.Titulo TituloAtual
        {
            get
            {
                return _tituloAtual;
            }
            set
            {
                _tituloAtual = value;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public bool HabilitaInclusaoOrdem
        {
            get { return this._habilitaInclusaoOrdem; }
            set { this._habilitaInclusaoOrdem = value; }
        }

        public ModelCollection<Model.Justificativa> JustificativasHistorico
        {
            get { return _justificativasHistorico; }
            set { _justificativasHistorico = value; }
        }

        public ModelCollection<Model.Justificativa> JustificativasRecente
        {
            get { return _justificativasRecente; }
            set { _justificativasRecente = value; }
        }

        #endregion Propriedades

        #region Construtores

        public ManutencaoOrdens(IManutencaoOrdens view)
            : base(view)
        {
            //Inicia Comm's
            _communicationCalendario = new Sinacor.UI.Bovespa.ManutencaoOrdens.Communication.Calendario(this.Session);
            _communicationJustificativa = new Sinacor.UI.Bovespa.ManutencaoOrdens.Communication.Justificativa(this.Session);
            _communicationManutencaoOrdens = new Sinacor.UI.Bovespa.ManutencaoOrdens.Communication.ManutencaoOrdens(this.Session);
            _communicationOperador = new Sinacor.UI.Bovespa.ManutencaoOrdens.Communication.Operador(this.Session);
            _communicationNegocio = new Sinacor.UI.Bovespa.ManutencaoOrdens.Communication.Negocio(this.Session);
            _communicationParametro = new Sinacor.UI.Bovespa.ManutencaoOrdens.Communication.Parametro(this.Session);
            _communicationMensagem = new Sinacor.UI.Bovespa.ManutencaoOrdens.Communication.Mensagem(this.Session);
            _communicationControleMovimentoOrdens = new Sinacor.UI.Bovespa.ManutencaoOrdens.Communication.ControleMovimentoOrdens(this.Session);
            _communicationTitulo = new Sinacor.UI.Bovespa.ManutencaoOrdens.Communication.Titulo(this.Session);
            _communicationCliente = new Sinacor.UI.Bovespa.ManutencaoOrdens.Communication.Cliente(this.Session);

            //Inicia Model Collections
            _filtroOrdens = new Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Parameter.FiltroOrdem();
            _emissores = new ModelCollection<Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Emissor>();
            _mensagensJustificativas = new ModelCollection<Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Mensagem>();
            _mensagensObservacoes = new ModelCollection<Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Mensagem>();
            _operadoresSubordinados = new ModelCollection<Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Operador>(); ;
            this.Ordens = new ModelCollection<Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Ordem>();
            _bolsas = new ModelCollection<Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Bolsa>();
            _calendarioFiltro = new ModelCollection<Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Calendario>();

            //Inicia Dicionarios
            _dicionarioValidadorPropriedadesOrdem = new Dictionary<string, bool>();

            _estado = Model.Enum.EstadoTela.Leitura;
        }

        #endregion Construtores

        #region Métodos

        /// <summary>
        /// Alterar Justificativa
        /// </summary>
        /// <param name="justificativa"></param>
        private void AlterarJustificativa(Model.Ordem ordem, Model.Justificativa justificativa)
        {
            try
            {
                this._communicationJustificativa.AlterarJustificativa(justificativa);
                ordem.Justificativas.Save(justificativa);
            }
            catch (Exception ex)
            {
                justificativa.AddError(ex);
            }
        }

        /// <summary>
        /// Verificar o diagrama de atividade ManutencaoOrdens.AlterarOrdem()
        /// </summary>
        /// <param name="ordem"></param>
        private void AlterarOrdem(ref Model.Ordem ordem)
        {
            Justificativa justificativa = null;
            ModelCollection<Model.Justificativa> justificativasInseridas = null;
            ModelCollection<Model.Justificativa> justificativasAlteradas = null;
            bool erroJustificativas = false;
            bool erroDetalhes = false;

            ordem.ClearErrors();

            try
            {
                if (ordem.Justificativas == null)
                {
                    this._communicationManutencaoOrdens.AlterarOrdem(ordem, justificativa);
                }
                else
                {
                    justificativasInseridas = ordem.Justificativas.GetInserted();

                    //Se for maior que zero ocorreu alguma mudança na ordem
                    //senão as modificações ocorridas foram apenas nas próprias justificativas
                    if (justificativasInseridas.Count > 0)
                    {
                        justificativa = justificativasInseridas[0];

                        //Altera a ordem
                        this._communicationManutencaoOrdens.AlterarOrdem(ordem, justificativa);

                        //Salva justificativa
                        ordem.Justificativas.Save(justificativa);
                    }
                }
            }
            catch (Exception ex)
            {                
                ordem.AddError(ex);
            }

            //Verifica se existe justificativas para a ordem
            if (ordem.Justificativas != null)
            {
                justificativasAlteradas = ordem.Justificativas.GetUpdated();

                //Percorre lista de justificativas a serem alteradas
                foreach (Justificativa justif in justificativasAlteradas)
                {
                    //Altera justificativa
                    AlterarJustificativa(ordem, justif);

                    if (!erroJustificativas
                        && justif.HasErrors)
                    {
                        erroJustificativas = true;
                    }
                }
            }

            //Verifica se ordem é do tipo Financiamento ou POP
            if ((ordem.TipoOrdem == Model.Enum.TipoOrdem.Financiamento) ||
                    (ordem.CodigoISIN != null && ordem.CodigoISIN.Substring(6, 2).ToUpper() == "PP"))
            {
                //Verifica se existe detalhes para a ordem
                if (ordem.Detalhes != null)
                {
                    //Percorre lista de detalhes da ordem a serem inseridos
                    foreach (DetalheOrdem detalhe in ordem.Detalhes.GetInserted())
                    {
                        this.IncluirDetalheOrdem(detalhe, ordem);

                        if (!detalhe.HasErrors)
                        {
                            if (ordem.CasarDetalhes)
                            {
                                CasarDetalhesOrdem(detalhe);
                            }
                        }
                        else if (!erroDetalhes)
                        {
                            erroDetalhes = true;
                        }

                    }

                    //Percorre lista de detalhes da ordem a serem cancelados
                    foreach (DetalheOrdem detalhe in ordem.Detalhes.GetDeleted())
                    {
                        this.CancelarDetalheOrdem(detalhe);
                    }
                }
            }

            if (!ordem.HasErrors
                && !erroJustificativas
                && !erroDetalhes)
            {
                //Salva ordem
                _ordens.Save(ordem);
            }
        }

        /// <summary>
        /// Aplica as alterações realizadas na alteração em lote, para todas as ordens selecionadas.
        /// </summary>
        public void AplicarAlteracaoLote()
        {
            System.Reflection.PropertyInfo info = null;
            object valor = null;
            Type tipo = typeof(Model.Ordem);

            foreach (string chave in _dicionarioValidadorPropriedadesOrdem.Keys)
            {
                info = tipo.GetProperty(chave);
                valor = info.GetValue(_ordemAtual, null);

                //Se o valor do campo era igual a todas as ordens então atribui
                //Se o valor do campo não era comum, mas é diferente de nulo, então atribui
                if (_dicionarioValidadorPropriedadesOrdem[chave]
                    || (!_dicionarioValidadorPropriedadesOrdem[chave]
                        && valor != null))
                {
                    //Esse if corrige uma exceção na lógica acima:
                    //Caso um campo não seja alterado, mas o usuário tenha passado o foco para o campo,
                    //este passa a ter o valor String.Empty que por ser diferente de null, passa pelo if acima
                    if (!_dicionarioValidadorPropriedadesOrdem[chave]
                        && valor is string
                        && String.IsNullOrEmpty((string)valor))
                        continue;

                    foreach (Model.Ordem ordem in _ordensAtuais)
                    {
                        info.SetValue(ordem, valor, null);
                    }
                }
            }
        }

        /// <summary>
        /// _quantidadeSumarizada.TotalCompra =  Realizar um SUM na propriedade Quantidade
        /// do objeto _ordemAtual.Detalhes, onde a Natureza da Operação for igual a Compra
        /// _quantidadeSumarizada.TotalVenda = Realizar um SUM na propriedade Quantidade do
        /// objeto _ordemAtual.Detalhes, onde a Natureza da Operação for igual a Venda
        /// </summary>
        public void CalcularQuantidadeNegocio()
        {
            int countSoma = 0;
            int countVenda = 0;
            foreach (DetalheOrdem det in _ordemAtual.Detalhes)
            {
                if (det.NaturezaOperacao == Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Enum.NaturezaOperacao.Compra
                    && det.State != State.Deleted)
                    countSoma += det.Quantidade;
                else
                    countVenda += det.Quantidade;
            }

            _quantidadeSumarizada = new QuantidadeNegocioSumarizada();

            _quantidadeSumarizada.TotalCompra = countSoma;
            _quantidadeSumarizada.TotalVenda = countVenda;

            this.View.AtualizarQuantidadesSumarizadas();

        }

        /// <summary>
        /// Realiza o cálculo do valor de uma determinada ordem
        /// </summary>
        /// <param name="ordem"></param>
        /// <returns></returns>
        public void CalcularValorOrdem(Model.Ordem ordem)
        {
            Model.ChaveOrdem request = null;

            try
            {
                if (_tituloAtual != null
                    && ordem.NumeroOrdem.HasValue
                    && ordem.NumeroOrdemSubSequencia.HasValue)
                {
                    request = new Model.ChaveOrdem();
                    request.DataOrdem = ordem.DataOrdem;
                    request.NumeroOrdem = ordem.NumeroOrdem.Value;
                    request.NumeroOrdemSubSequencia = ordem.NumeroOrdemSubSequencia.Value;

                    ordem.ValorOrdem = _communicationManutencaoOrdens.CalcularValorOrdem(request);
                }
                else
                {
                    ordem.ValorOrdem = null;
                }
            }
            catch (Exception ex)
            {
                base.HandleException(ex);
            }
        }

        /// <summary>
        /// Recalcula o valor da ordem
        /// </summary>
        public void RecalcularValorOrdem()
        {
            Model.Titulo titulo = null;

            if (_ordemAtual.Quantidade.HasValue
                && _ordemAtual.QuantidadeExecutada.HasValue
                && _ordemAtual.ValorOrdem != null)
            {
                if (_tituloAtual != null)
                    titulo = _tituloAtual;
                else if (_ordemAtual.Ativo != null)
                    titulo = _communicationTitulo.ObterTitulo(new Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Parameter.FiltroTitulo() { CodigoNegocio = _ordemAtual.Ativo, DataPregao = _ordemAtual.DataOrdem });

                if (titulo != null
                    && titulo.CotacaoMediaTitulo.HasValue
                    && titulo.FatorCotacao.HasValue)
                {
                    _ordemAtual.ValorOrdem.ValorNaoExecutado = ((_ordemAtual.Quantidade - _ordemAtual.QuantidadeExecutada) * _tituloAtual.CotacaoMediaTitulo) / _tituloAtual.FatorCotacao;
                    _ordemAtual.ValorOrdem.ValorTotal = _ordemAtual.ValorOrdem.ValorNaoExecutado + _ordemAtual.ValorOrdem.ValorExecutado;
                }

                View.AtualizarValorOrdem();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public void VerificarOrdemFinanciamentoPOP()
        {
            if (_ordensAtuais == null)
            {
                if (_ordemAtual != null)
                    if ((_ordemAtual.TipoOrdem == Model.Enum.TipoOrdem.Financiamento) ||
                        (_ordemAtual.CodigoISIN != null && _ordemAtual.CodigoISIN.Substring(6, 2).ToUpper() == "PP"))
                    {
                        base.View.HabilitarAbaFinanciamentoPOP();
                    }
                    else
                    {
                        base.View.DesabilitarAbaFinanciamentoPOP();
                    }
                else
                {
                    base.View.DesabilitarAbaFinanciamentoPOP();
                }
            }
            else
            {
                base.View.DesabilitarAbaFinanciamentoPOP();
            }
        }

        /// <summary>
        /// Cancelar Detalhe Ordem
        /// </summary>
        /// <param name="detalheOrdem"></param>
        private void CancelarDetalheOrdem(Model.DetalheOrdem detalheOrdem)
        {
            try
            {
                ChaveOrdem chave = new ChaveOrdem
                {
                    DataOrdem = detalheOrdem.DataOrdem,
                    NumeroOrdem = detalheOrdem.NumeroOrdem.HasValue ? detalheOrdem.NumeroOrdem.Value : 0,
                    NumeroOrdemSubSequencia = detalheOrdem.NumeroOrdemSubSequencia.HasValue ? detalheOrdem.NumeroOrdemSubSequencia.Value : 0
                };

                _communicationManutencaoOrdens.CancelarDetalheOrdem(chave);

                _ordemAtual.Detalhes.Save(detalheOrdem);
            }
            catch (Exception ex)
            {
                detalheOrdem.AddError(ex);
            }
        }

        /// <summary>
        /// Verificar o diagrama de atividade ManutencaoOrdens.CancelarOrdem()
        /// </summary>
        /// <param name="ordem"></param>
        private void CancelarOrdem(ref Model.Ordem ordem)
        {
            Justificativa justificativa = null;
            ChaveOrdem chave = null;
            ordem.ClearErrors();

            try
            {
                if (ordem.Justificativas != null && ordem.Justificativas.GetInserted().Count > 0)
                {
                    justificativa = ordem.Justificativas.GetInserted().First();
                }

                chave = new ChaveOrdem
                {
                    DataOrdem = ordem.DataOrdem,
                    NumeroOrdem = ordem.NumeroOrdem.HasValue ? ordem.NumeroOrdem.Value : 0,
                    NumeroOrdemSubSequencia = ordem.NumeroOrdemSubSequencia.HasValue ? ordem.NumeroOrdemSubSequencia.Value : 0
                };

                _communicationManutencaoOrdens.CancelarOrdem(chave, justificativa);

                _ordens.Save(ordem);
            }
            catch (Exception ex)
            {
                ordem.AddError(ex);
            }
        }

        /// <summary>
        /// Carrega o dicionário com as propriedades da entidade ordem
        /// </summary>
        private void CarregarDicionarioValidador()
        {
            _dicionarioValidadorPropriedadesOrdem.Add("Situacao", true);
            _dicionarioValidadorPropriedadesOrdem.Add("Carteira", true);
            _dicionarioValidadorPropriedadesOrdem.Add("DataValidade", true);
            _dicionarioValidadorPropriedadesOrdem.Add("NaturezaOperacao", true);
            _dicionarioValidadorPropriedadesOrdem.Add("TipoOrdem", true);
            _dicionarioValidadorPropriedadesOrdem.Add("Discricionaria", true);
            _dicionarioValidadorPropriedadesOrdem.Add("ValorFinanciamento", true);
            _dicionarioValidadorPropriedadesOrdem.Add("PercentualFinanciamento", true);
            _dicionarioValidadorPropriedadesOrdem.Add("CodigoCliente", true);
            _dicionarioValidadorPropriedadesOrdem.Add("CodigoBrokerCliente", true);
            _dicionarioValidadorPropriedadesOrdem.Add("Ativo", true);
            _dicionarioValidadorPropriedadesOrdem.Add("NomeEmissor", true);
            _dicionarioValidadorPropriedadesOrdem.Add("PrazoVencimentoTermo", true);
            _dicionarioValidadorPropriedadesOrdem.Add("Mercado", true);
            _dicionarioValidadorPropriedadesOrdem.Add("CodigoBolsa", true);
            _dicionarioValidadorPropriedadesOrdem.Add("Quantidade", true);
            _dicionarioValidadorPropriedadesOrdem.Add("Preco", true);
            _dicionarioValidadorPropriedadesOrdem.Add("CodigoOperador", true);
            _dicionarioValidadorPropriedadesOrdem.Add("QuantidadeAnexoIV", true);
            _dicionarioValidadorPropriedadesOrdem.Add("QuantidadeAnexoV", true);
            _dicionarioValidadorPropriedadesOrdem.Add("ValorDolar", true);
            _dicionarioValidadorPropriedadesOrdem.Add("IndicadorDesprezaSaldo", true);
            _dicionarioValidadorPropriedadesOrdem.Add("IndicadorSistemaExterno", true);
            _dicionarioValidadorPropriedadesOrdem.Add("TipoLiquidacao", true);
            _dicionarioValidadorPropriedadesOrdem.Add("NumeroOrdemOriginal", true);
            _dicionarioValidadorPropriedadesOrdem.Add("IndicadorOrdemAdmConcorrente", true);
            _dicionarioValidadorPropriedadesOrdem.Add("IndicadorClientePessoaVinculada", true);
            _dicionarioValidadorPropriedadesOrdem.Add("PercentualCorretagem", true);
            _dicionarioValidadorPropriedadesOrdem.Add("DataFormatada", true);
            _dicionarioValidadorPropriedadesOrdem.Add("ApelidoCliente", true);
            _dicionarioValidadorPropriedadesOrdem.Add("DigitoCliente", true);
            _dicionarioValidadorPropriedadesOrdem.Add("CodigoISIN", true);
            _dicionarioValidadorPropriedadesOrdem.Add("DescricaoAtivo", true);
            _dicionarioValidadorPropriedadesOrdem.Add("Observacao", true);
        }

        /// <summary>
        /// Chamar o método da Infra EnumWrapper&lt;Enum.NaturezaOperacao&gt;.GetEnums() e
        /// atribuir retorno ao atributo _listaNaturezaOperacao.
        /// </summary>
        public void CarregarNaturezaOperacao()
        {
            _listaNaturezaOperacao = EnumWrapper<Model.Enum.NaturezaOperacao>.GetEnums(Model.Enum.NaturezaOperacao.Compra,
                                                                                       Model.Enum.NaturezaOperacao.Venda);

            this.ListaNaturezaOperacaoDetalhe = EnumWrapper<Model.Enum.NaturezaOperacao>.GetEnums(Model.Enum.NaturezaOperacao.Compra,
                                                                                                  Model.Enum.NaturezaOperacao.Venda);
        }

        /// <summary>
        /// Chamar o método da Infra EnumWrapper&lt;Enum.TipoMercado&gt;.GetEnums() e
        /// atribuir retorno ao atributo _listaTipoMercado.
        /// </summary>
        private void CarregarTipoMercado()
        {
            _tiposMercados = EnumWrapper<Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Enum.TipoMercado>.GetEnums(
                Model.Enum.TipoMercado.BOX,
                Model.Enum.TipoMercado.CotasETF,
                Model.Enum.TipoMercado.Estruturado,
                Model.Enum.TipoMercado.ExercicioOpcaoCompra,
                Model.Enum.TipoMercado.ExercicioOpcaoVenda,
                Model.Enum.TipoMercado.Fracionario,
                Model.Enum.TipoMercado.Futuro,
                Model.Enum.TipoMercado.IntegralizacaoResgateCotas,
                Model.Enum.TipoMercado.Leilao,
                Model.Enum.TipoMercado.LeilaoNaoCotados,
                Model.Enum.TipoMercado.OpcaoCompra,
                Model.Enum.TipoMercado.OpcaoVenda,
                Model.Enum.TipoMercado.Termo,
                Model.Enum.TipoMercado.VencimentoFuturo,
                Model.Enum.TipoMercado.Vista);
        }

        /// <summary>
        /// <b>Se </b>_ordemAtual.TipoOrdem == Financiamento
        ///   Chamar o método da Infra EnumWrapper&lt;Enum.TipoMercado&gt;.GetEnums(Vista,
        /// Termo)
        /// <b>Senão</b>
        /// <b>   Se</b> _ordemAtual.TipoOrdem == POP
        ///      Chamar o método da Infra EnumWrapper&lt;Enum.TipoMercado&gt;.
        /// GetEnums(Vista,Opção Compra, Opção Venda)
        /// <b>Fim Se
        /// </b><b>Fim Se</b>
        /// </summary>
        public void CarregarTipoMercadoDetalhe()
        {
            if (this._ordemAtual.TipoOrdem.Value == Model.Enum.TipoOrdem.Financiamento)
            {
                this.TiposMercadosDetalhes = EnumWrapper<Model.Enum.TipoMercado>.GetEnums(Model.Enum.TipoMercado.Vista,
                                                                                          Model.Enum.TipoMercado.Termo);
            }
            else
            {
                this.TiposMercadosDetalhes = EnumWrapper<Model.Enum.TipoMercado>.GetEnums(Model.Enum.TipoMercado.Vista,
                                                                                          Model.Enum.TipoMercado.OpcaoCompra,
                                                                                          Model.Enum.TipoMercado.OpcaoVenda);
            }
        }

        /// <summary>
        /// Chamar o método da Infra EnumWrapper&lt;Enum.TipoOrdem&gt;.GetEnums() e
        /// atribuir retorno ao atributo _listaTipoOrdem.
        /// </summary>
        private void CarregarTipoOrdem()
        {
            _tiposOrdens = EnumWrapper<Model.Enum.TipoOrdem>.GetEnums();
        }

        private void CarregarTiposSituacao()
        {
            _tiposSituacao = EnumWrapper<Model.Enum.SituacaoOrdem>.GetEnums();
        }

        private void CarregarTiposLiquidacao()
        {
            _tiposLiquidacao = EnumWrapper<Model.Enum.TipoLiquidacao>.GetEnums();
        }

        /// <summary>
        /// Casar Detalhes Ordem
        /// </summary>
        /// <param name="ordem"></param>
        private void CasarDetalhesOrdem(Model.DetalheOrdem detalheOrdem)
        {
            try
            {
                ChaveOrdem chaveOrdem = new ChaveOrdem
                {
                    DataOrdem = detalheOrdem.DataOrdem,
                    NumeroOrdem = detalheOrdem.NumeroOrdem.HasValue ? detalheOrdem.NumeroOrdem.Value : 0,
                    NumeroOrdemSubSequencia = detalheOrdem.NumeroOrdemSubSequencia.HasValue ? detalheOrdem.NumeroOrdemSubSequencia.Value : 0
                };

                _communicationManutencaoOrdens.CasarDetalhesOrdem(chaveOrdem);

                _ordemAtual.Detalhes.Save(detalheOrdem);
            }
            catch (Exception ex)
            {
                detalheOrdem.AddError(ex);
            }
        }

        public void ApresentarCliente()
        {
            if (this._clienteAtual != null)
            {
                // Obter emissor(es) do _clienteAtual
                this._emissores = this.ConsultarEmissor(_clienteAtual);

                // Atualiza combo de emissor
                this.View.AtualizarEmissor();

                // Atribuir ao campo NomeCliente da ordem o Nome + Complemento do _clienteAtual obtido
                this.View.ApresentarNomeCliente(String.Format("{0} {1}", _clienteAtual.Nome, _clienteAtual.ComplementoNome));

                // Atribuir para a ordem o broker do _clienteAtual
                this.View.ApresentarBrokerCliente(_clienteAtual.Broker);

                // Atribuir à ordem o dígito verificador do _clienteAtual
                if (this._parametros.IndicadorDigitoCliente.Equals("N"))
                    this.View.ApresentarDigitoCliente(_clienteAtual.Digito.Value);
            }
        }

        /// <summary>
        /// Método serve para configurar a ordem conforme dados obtidos do cliente
        /// informado pelo usuário.
        /// </summary>
        /// <param name="cliente"></param>
        public void ConfigurarCliente()
        {
            if (this._clienteAtual != null)
            {
                ApresentarCliente();

                // Cliente é administrado concorrente e o sistema está
                // parametrizado para utilização de adminstrado concorrente?
                if (_clienteAtual.AdministradoConcorrente 
                    && this._parametros.IndicadorAdministradoConcorrente)
                {
                    //Atribuir ordem como administrada concorrente
                    View.AtribuirOrdemAdministradaConcorrente(true);
                    //Atribuir tipo da ordem como administrada
                    View.AtribuirTipoOrdem(Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Enum.TipoOrdem.Administrada);
                    //Atribuir ordem como discricionária
                    View.AtribuirOrdemDiscricionaria(true);
                }
                else
                {
                    //Atribuir ordem não administrada concorrente
                    View.AtribuirOrdemAdministradaConcorrente(false);
                }

                //Cliente é pessoa vinculada?
                if (_clienteAtual.PessoaVinculada)
                {
                    //Atribuir ordem como pessoa vinculada
                    View.AtribuirPessoaVinculada(true);
                }
                else
                {
                    //Atribuir ordem como pessoa não vinculada
                    View.AtribuirPessoaVinculada(false);
                }

                //Percentual de corretagem total é diferente de zero?
                if ((decimal)_clienteAtual.PercentualCorretagemTotal != 0)
                {
                    //Atribuir percentual de acréscimo e redução (corretagem)
                    //igual a percentual de corretagem principal
                    View.AtribuirPercentualCorretagem(_clienteAtual.PercentualCorretagemPrincipal);
                }
                else
                {
                    //Atribuir percentual de acréscimo e redução (corretagem)
                    //igual à percentual da corretagem total
                    View.AtribuirPercentualCorretagem(_clienteAtual.PercentualCorretagemTotal);
                }

                if (this._ordemAtual != null)
                {
                    //Preenchimento automático do tipo de liquidação parametrizado 
                    //E Mercado não é derivativo 
                    //E o _clienteAtual possui custodiante ou usuário Institucional?
                    if (
                            this._parametros.TipoLiquidacaoCAutomatica &&
                           (this._ordemAtual.Mercado != Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Enum.TipoMercado.Vista ||
                            this._ordemAtual.Mercado != Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Enum.TipoMercado.Leilao ||
                            this._ordemAtual.Mercado != Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Enum.TipoMercado.ExercicioOpcaoCompra ||
                            this._ordemAtual.Mercado != Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Enum.TipoMercado.ExercicioOpcaoVenda ||
                            this._ordemAtual.Mercado != Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Enum.TipoMercado.Fracionario) &&
                            (_clienteAtual.CodigoClienteInstitucional != null || _clienteAtual.CodigoCustodiante != null)
                       )
                    {
                        //Atribuir a ordem tipo de liquidação igual a custodiante
                        View.AtribuirTipoLiquidacao(Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Enum.TipoLiquidacao.Custodiante);
                    }
                    else
                    {
                        //Atribuir a ordem tipo de liquidação igual a normal
                        View.AtribuirTipoLiquidacao(Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Enum.TipoLiquidacao.Normal);
                    }
                }

                //Cliente é broker?
                if (_clienteAtual.ClienteBroker)
                {
                    //Atribuir ordem como discricionária
                    View.AtribuirOrdemDiscricionaria(true);
                }
            }
        }

        /// <summary>
        /// Verificar o diagrama de atividade ManutencaoOrdens.ConfigurarMercado()
        /// </summary>
        /// <param name="mercado"></param>
        public void ConfigurarMercado(Model.Enum.TipoMercado mercado)
        {
            this.View.AtribuirVencimentoTermoObrigatorio(false);

            if (mercado == Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Enum.TipoMercado.CotasETF ||
                mercado == Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Enum.TipoMercado.IntegralizacaoResgateCotas)
            {
                View.AtribuirOrdemDiscricionaria(false);
            }
            else if (mercado == Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Enum.TipoMercado.Termo)
                this.View.AtribuirVencimentoTermoObrigatorio(true);
        }

        /// <summary>
        /// Configurar ordem atual para casar (_ordemAtual.CasarDetalhes = true;)
        /// </summary>
        public void ConfigurarOrdemCasarDetalhes()
        {
            this._ordemAtual.CasarDetalhes = true;
        }

        /// <summary>
        /// Verificar o diagrama de atividade ManutencaoOrdens.ConfigurarTipoOrdem()
        /// </summary>
        /// <param name="tipo"></param>
        public void ConfigurarTipoOrdem(Model.Enum.TipoOrdem tipo)
        {
            if (tipo == Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Enum.TipoOrdem.Financiamento)
            {
                this.View.AtribuirMercado(Model.Enum.TipoMercado.Termo);
                this.View.DesabilitarMercado();
                this.View.DesabilitarNaturezaOperacao();
                this.View.DesabilitarCarteira();
                this.View.AtribuirValorFinanciamentoObrigatorio(true);
                this.View.AtribuirPercentualFinanciamentoObrigatorio(true);
                this.View.AtribuirQuantidadeOrdemTipoFinanciamento();
                this.View.HabilitarAbaFinanciamentoPOP();
                this.View.DesabilitarAtivo();
                this.LimparDetalhes();
                
                _tituloAtual = null;
            }
            else
            {
                if (this._tituloAtual != null && this._tituloAtual.Isin.Substring(6, 2) != "PP")
                {
                    this.View.DesabilitarAbaFinanciamentoPOP();
                    this.LimparDetalhes();
                }

                this.View.AtribuirValorFinanciamentoObrigatorio(false);
                this.View.AtribuirPercentualFinanciamentoObrigatorio(false);
                this.View.HabilitarCampoQuantidade();
                this.View.HabilitarCarteira();
                this.View.HabilitarNaturezaOperacao();
                this.View.HabilitarAtivo();

                this.View.HabilitarMercado();
            }
        }

        /// <summary>
        /// Método que verifica se o dígito verificador é obrigatório
        /// </summary>
        public void VerificarDigitoVerificadorObrigatorio()
        {
            if (_parametros.IndicadorDigitoCliente.Equals("S"))
            {
                this.View.ConfigurarDigitoVerificadorObrigatorio();
            }
        }

        /// <summary>
        /// Método serve para configurar a ordem conforme dados obtidos do ativo informado
        /// pelo usuário.
        /// 
        /// Verificar o diagrama de atividade ManutencaoOrdens.ConfigurarTitulo()
        /// </summary>
        /// <param name="titulo"></param>
        public void ConfigurarTitulo()
        {
            if (this._tituloAtual != null 
                && this._ordemAtual != null)
            {
                View.ApresentarDescricaoTitulo(_tituloAtual.Descricao);
                View.AtribuirCodigoISIN(_tituloAtual.Isin);

                if (this._tituloAtual.Isin.Substring(6, 2) == "PP" 
                    || (this._ordemAtual.TipoOrdem != null 
                        && this._ordemAtual.TipoOrdem.Value == Model.Enum.TipoOrdem.Financiamento))
                    this.View.HabilitarAbaFinanciamentoPOP();
                else
                {
                    this.View.DesabilitarAbaFinanciamentoPOP();
                    this.LimparDetalhes();
                }
            }
        }

        /// <summary>
        /// Verificar o diagrama de atividade ManutencaoOrdens.Inicializar()
        /// </summary>
        private ModelCollection<Model.Bolsa> ConsultarBolsas()
        {
            return _communicationNegocio.ConsultarBolsas();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private ModelCollection<Model.Calendario> ConsultarCalendario()
        {
            return _communicationCalendario.ConsultarCalendario();
        }

        /// <summary>
        /// 1º)  Se _ordemAtual.TipoDistribuicaoPermitida == DiferenciadoPOP || _ordemAtual.
        /// TipoDistribuicaoPermitida == DiferenciadoAdministradoConcorrentePOP ||
        /// _ordemAtual.TipoOrdem == Financiamento
        /// Chamar o método <font color="#0000ff">_communicationManutencaoOrdens</font>.
        /// <b>ConsultarDetalhesOrdem()</b>, passando como parâmetro de entrada o atributo
        /// _ordemAtual.
        /// 2º) Armazenar o retorno na propriedade Detalhes do atributo _ordemAtual.
        /// </summary>
        public void ConsultarDetalhesOrdem()
        {
            ChaveOrdem req = new ChaveOrdem()
                {
                    NumeroOrdem = _ordemAtual.NumeroOrdem.Value,
                    DataOrdem = _ordemAtual.DataOrdem,
                    NumeroOrdemSubSequencia = _ordemAtual.NumeroOrdemSubSequencia.Value
                };

            _ordemAtual.Detalhes = _communicationManutencaoOrdens.ConsultarDetalhesOrdem(req);

            this.CalcularQuantidadeNegocio();
            this.View.AtualizarDetalhesOrdem();
        }

        /// <summary>
        /// Criar um objeto do tipo Model.Parameter.FiltroEmissor e atribuir o código do
        /// cliente recebido como parâmetro de entrada para o filtro
        /// Chamar o método <font color="#0000ff">Communication.Cliente</font>.
        /// <b>ConsultarEmissorOrdem()</b>
        /// </summary>
        /// <param name="cliente"></param>
        private ModelCollection<Model.Emissor> ConsultarEmissor(Model.Cliente cliente)
        {
            //Criar um objeto do tipo Model.Parameter.FiltroEmissor e atribuir o código do cliente recebido como parâmetro de entrada para o filtro
            Model.Parameter.FiltroEmissor filtroEmissor = new Model.Parameter.FiltroEmissor() { CodigoCliente = (int)cliente.Codigo };

            //Chamar o método Communication.Cliente.ConsultarEmissorOrdem()
            return _communicationCliente.ConsultarEmissorOrdem(filtroEmissor);
        }

        /// <summary>
        /// Retorno da lista de Justificativas das ordens recebida como parâmetro de entrada 
        /// (Inicialmente concebido para tratar os casos envolvidos na Alteração em Lote 
        /// onde é necessário alimentar as Justificativas das ordens envolvidas, ao invés da OrdemAtual)
        /// </summary>
        /// <param name="ordem"></param>
        /// <returns></returns>
        public void ConsultarJustificativas(ModelCollection<Model.Ordem> ordens)
        {
            ModelCollection<Model.Justificativa> retornoPesquisa;
            int contadorPendenteMensageria;
            int ultimoIndiceAux;
            Model.Justificativa justificativaRetorno;

            retornoPesquisa = _communicationJustificativa.ConsultarJustificativas(ref ordens);

            foreach (Model.Ordem ordem in ordens)
            {
                contadorPendenteMensageria = 0;

                for (int i = retornoPesquisa.Count - 1; i >= 0; i--)
                {
                    justificativaRetorno = retornoPesquisa[i];

                    if (ordem.DataOrdem == justificativaRetorno.DataOrdem
                       && ordem.NumeroOrdem == justificativaRetorno.NumeroOrdem
                       && ordem.NumeroOrdemSubSequencia == justificativaRetorno.NumeroSubSequenciaOrdem)
                    {
                        if (justificativaRetorno.PendenteMensageria)
                        {
                            justificativaRetorno.CodigoPendenteMensageria = contadorPendenteMensageria;
                            contadorPendenteMensageria++;
                        }

                        ordem.Justificativas.Add(justificativaRetorno);

                        //Realiza o clone para evitar a criação de referência com a model presente na ordem.Justificativas
                        _justificativasHistorico.Add((Model.Justificativa)Infra.Common.Serialization.CloneHelper.Clone(justificativaRetorno));

                        ultimoIndiceAux = _justificativasHistorico.Count - 1;

                        //Remove o status de Inserted
                        _justificativasHistorico.Save(ultimoIndiceAux);

                        //Remove o item para as próximas iterações do laço de repetição serem mais eficientes
                        retornoPesquisa.RemoveAt(i);
                    }
                }

                ordem.Justificativas.EnableStateControl = true;
            }
        }

        public Model.Justificativa ObterJustificativa(Model.Parameter.FiltroJustificativa filtro)
        {
            return _communicationJustificativa.ObterJustificativa(filtro);
        }

        /// <summary>
        /// Consulta as justificativas referentes as ordenes selecionads e as classifica em Recente ou Histórico
        /// para que seja populada a aba de justificativas
        /// </summary>
        /// <param name="ordem"></param>
        public void CompilarJustificativas()
        {
            int ultimoIndice;
            State estado;
            ModelCollection<Model.Ordem> ordensPesquisar = new ModelCollection<Ordem>();

            if (_ordemAtual != null)
            {
                CompilarJustificativas(_ordemAtual, ordensPesquisar);
            }
            else if (_ordensAtuais != null)
            {
                foreach(Model.Ordem ordem in _ordensAtuais)
                {
                    CompilarJustificativas(ordem, ordensPesquisar);
                }
            }

            ConsultarJustificativas(ordensPesquisar);

            var ordernacaoJustificativas = from just in _justificativasRecente
                                           orderby just.DataOrdem, just.NumeroOrdem, just.NumeroSubSequenciaOrdem, just.DataAlteracao, just.CodigoPendenteMensageria
                                           select just;

            _justificativasRecente = new ModelCollection<Model.Justificativa>();
            _justificativasRecente.EnableStateControl = true;

            foreach (Model.Justificativa justificativa in ordernacaoJustificativas)
            {
                _justificativasRecente.Add(justificativa);
            }

            ordernacaoJustificativas = from just in _justificativasHistorico
                                       orderby just.DataOrdem, just.NumeroOrdem, just.NumeroSubSequenciaOrdem, just.Codigo, just.DataAlteracao, just.CodigoPendenteMensageria
                                       select just;

            _justificativasHistorico = new ModelCollection<Model.Justificativa>();
            _justificativasHistorico.EnableStateControl = true;

            foreach (Model.Justificativa justificativa in ordernacaoJustificativas)
            {
                estado = justificativa.State;

                _justificativasHistorico.Add(justificativa);

                ultimoIndice = _justificativasHistorico.Count-1;

                _justificativasHistorico.Save(ultimoIndice);

                if (estado == State.Updated)
                {
                    _justificativasHistorico[ultimoIndice] = (Model.Justificativa)Infra.Common.Serialization.CloneHelper.Clone(_justificativasHistorico[ultimoIndice]);
                }
            }

            View.AtualizarJustificativas();
        }

        private void CompilarJustificativas(Model.Ordem ordem, ModelCollection<Model.Ordem> ordensPesquisar)
        {
            int ultimoIndiceAux;

            if (ordem.NumeroOrdem.HasValue
                           && ordem.NumeroOrdemSubSequencia.HasValue)
            {
                if (!ordem.CacheJustificativasConsultadas)
                {
                    if (ordem.Justificativas != null)
                    {
                        foreach (Model.Justificativa justificativa in ordem.Justificativas.GetInserted())
                        {
                            //Realiza o clone para evitar a criação de referência com a model presente na ordem.Justificativas
                            _justificativasRecente.Add((Model.Justificativa)Infra.Common.Serialization.CloneHelper.Clone(justificativa));
                        }
                    }

                    ordem.CacheJustificativasConsultadas = true;
                    ordem.Justificativas = new ModelCollection<Justificativa>();

                    ordensPesquisar.Add(ordem);
                }
                else
                {
                    foreach (Model.Justificativa justificativa in ordem.Justificativas)
                    {
                        if (justificativa.State == State.Inserted)
                        {
                            //Realiza o clone para evitar a criação de referência com a model presente na ordem.Justificativas
                            _justificativasRecente.Add((Model.Justificativa)Infra.Common.Serialization.CloneHelper.Clone(justificativa));
                        }
                        else
                        {
                            //Realiza o clone para evitar a criação de referência com a model presente na ordem.Justificativas
                            _justificativasHistorico.Add((Model.Justificativa)Infra.Common.Serialization.CloneHelper.Clone(justificativa));

                            ultimoIndiceAux = _justificativasHistorico.Count - 1;

                            //Remove o status de Inserted
                            _justificativasHistorico.Save(ultimoIndiceAux);

                            if (justificativa.State == State.Updated)
                            {
                                //Força o status de Update e cria a opção de undo através do clone
                                _justificativasHistorico[ultimoIndiceAux] = (Model.Justificativa)Infra.Common.Serialization.CloneHelper.Clone(_justificativasHistorico[ultimoIndiceAux]);
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Analisa as justificativas (recentes e histórico) e reflete suas possíveis mudanças
        /// nas coleções de justificativas presentes em cada ordem
        /// </summary>
        public void SincronizarJustificativas()
        {
            if (_ordemAtual != null)
            {
                SincronizarJustificativas(_ordemAtual);
            }
            else if (_ordensAtuais != null)
            {
                for (int i = 0; i < _ordensAtuais.Count; i++)
                {
                    SincronizarJustificativas(_ordensAtuais[i]);
                }
            }

            _justificativasHistorico.Clear();
            _justificativasRecente.Clear();

            View.AtualizarJustificativas();
        }

        /// <summary>
        /// Analisa as justificativas (recentes e histórico) e reflete suas possíveis mudanças
        /// nas coleções de justificativas presentes em cada ordem
        /// </summary>
        private void SincronizarJustificativas(Model.Ordem ordem)
        {
            int index;
            ModelCollection<Model.Justificativa> justificativaInserida;

            for (int i = _justificativasRecente.Count - 1; i >= 0; i--)
            {
                if (ordem.DataOrdem == _justificativasRecente[i].DataOrdem
                    && ordem.NumeroOrdem == _justificativasRecente[i].NumeroOrdem
                    && ordem.NumeroOrdemSubSequencia == _justificativasRecente[i].NumeroSubSequenciaOrdem)
                {
                    justificativaInserida = ordem.Justificativas.GetInserted();

                    if (justificativaInserida != null
                        && justificativaInserida.Count > 0)
                    {
                        justificativaInserida[0].JustificativaOrdem = _justificativasRecente[i].JustificativaOrdem;
                    }
                    else
                    {
                        ordem.Justificativas.Add(_justificativasRecente[i]);
                    }

                    //Remove da lista para que as próximas chamadas ao método
                    //para a análise de outras ordens seja mais rápida
                    _justificativasRecente.RemoveAt(i);
                    _justificativasRecente.Save(i);

                    //Existe apenas uma justificativa recente para cada ordem
                    break;
                }
            }

            //Para que os clones tenham efeito e gerem histórico para realização de undo:
            //obtém o índice para manipular a ordem diretamente
            //na coleção ao invés de manipular o objeto passado como parâmetro
            index = _ordens.IndexOf(ordem);

            for (int j = 0; j < _ordens[index].Justificativas.Count; j++)
            {
                for (int i = _justificativasHistorico.Count - 1; i >= 0; i--)
                {
                    if (_justificativasHistorico[i].DataOrdem == _ordens[index].Justificativas[j].DataOrdem
                         && _justificativasHistorico[i].NumeroOrdem == _ordens[index].Justificativas[j].NumeroOrdem
                         && _justificativasHistorico[i].NumeroSubSequenciaOrdem == _ordens[index].Justificativas[j].NumeroSubSequenciaOrdem
                         && _justificativasHistorico[i].Codigo == _ordens[index].Justificativas[j].Codigo
                         && (!_justificativasHistorico[i].PendenteMensageria
                            || (_justificativasHistorico[i].PendenteMensageria
                                && _justificativasHistorico[i].CodigoPendenteMensageria == _ordens[index].Justificativas[j].CodigoPendenteMensageria)))
                    {
                        if (_justificativasHistorico[i].State == State.Updated) //A justificativa foi modificada e precisa ser atualizada na coleção dentro da ordem
                        {
                            if (_ordens[index].State != State.Updated)
                            {
                                _ordens[index] = (Model.Ordem)Infra.Common.Serialization.CloneHelper.Clone(_ordens[index]);
                                View.SelecionarOrdem(_ordens[index]);
                            }

                            _ordens[index].Justificativas[j] = (Model.Justificativa)Infra.Common.Serialization.CloneHelper.Clone(_justificativasHistorico[i]);
                        }
                        else if (_justificativasHistorico[i].State == State.Unchanged
                                && _ordens[index].Justificativas[j].State == State.Updated) //A justificativa sofre undo e precisa ser atualizada na coleção dentro da ordem
                        {
                            _ordens[index].Justificativas[j] = _ordens[index].Justificativas[j] = (Model.Justificativa)Infra.Common.Serialization.CloneHelper.Clone(_justificativasHistorico[i]);
                            _ordens[index].Justificativas.Save(j);
                        }

                        //Remove da lista para que as próximas chamadas ao método
                        //para a análise de outras ordens seja mais rápida
                        _justificativasHistorico.RemoveAt(i);
                        _justificativasHistorico.Save(i);

                        break;
                    }
                }
            }
        }

        /// <summary>
        /// Realizar o Undo da Justificativa passada como parâmetro
        /// e a atualizar a coleção _justificativasHistorico
        /// </summary>
        /// <param name="justificativa"></param>
        public void DesfazerJustificativa(Model.Justificativa justificativa)
        {
            Model.Parameter.FiltroJustificativa filtro;

            if (!justificativa.PendenteMensageria)
            {
                filtro = new Model.Parameter.FiltroJustificativa
                {
                    Codigo = justificativa.Codigo.Value,
                    DataOrdem = justificativa.DataOrdem,
                    NumeroOrdem = justificativa.NumeroOrdem,
                    NumeroOrdemSubSequencia = justificativa.NumeroSubSequenciaOrdem
                };

                justificativa = ObterJustificativa(filtro);
            }
            else
            {
                justificativa.JustificativaOrdem = null;
            }

            for (int j = 0; j < _justificativasHistorico.Count; j++)
            {
                if (justificativa.Codigo == _justificativasHistorico[j].Codigo
                   && justificativa.DataOrdem == _justificativasHistorico[j].DataOrdem
                   && justificativa.NumeroOrdem == _justificativasHistorico[j].NumeroOrdem
                   && justificativa.NumeroSubSequenciaOrdem == _justificativasHistorico[j].NumeroSubSequenciaOrdem
                   && (!justificativa.PendenteMensageria
                       || (justificativa.PendenteMensageria
                           && justificativa.CodigoPendenteMensageria == _justificativasHistorico[j].CodigoPendenteMensageria)))
                {
                    _justificativasHistorico[j] = justificativa;
                    _justificativasHistorico.Save(j);
                    break;
                }
            }
         
            View.AtualizarJustificativas();
        }

        /// <summary>
        /// Chamar o método _communicationMensagem.
        /// ConsultarMensagensJustificativaObservacao(), passando como parâmetro de entrada
        /// TipoSistema igual a Ordem
        /// </summary>
        private ModelCollection<Model.Mensagem> ConsultarMensagens()
        {
            Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Parameter.FiltroMensagemJustificativaObservacao req =
                new Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Parameter.FiltroMensagemJustificativaObservacao();

            req.TipoSistema = Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Enum.TipoSistema.Ordem;

            return _communicationMensagem.ConsultarMensagensJustificativaObservacao(req);
        }

        /// <summary>
        /// ConsultarOrdens
        /// </summary>
        public void ConsultarOrdens()
        {
            //Importante:
            //As propriedades PermiteCasamento e
            //Distribuida devem estar com valor igual
            //a nulo.
            try
            {
                this.Ordens = _communicationManutencaoOrdens.ConsultarOrdens(_filtroOrdens);

                if (_ordens == null || _ordens.Count == 0)
                {
                    base.View.InformarNenhumaOrdemEncontrada();
                }

                base.View.AtualizarOrdens();
            }
            catch (Exception ex)
            {
                base.HandleException(ex);
            }
        }

        /// <summary>
        /// Chamar o método <font color="#0000ff">_communicationOperador</font>.
        /// ConsultarSubordinados().
        /// Realizar um filtro no retorno retirando todos os subordinados que estiverem
        /// bloqueados (Bloqueado = true)
        /// </summary>
        private ModelCollection<Model.Operador> ConsultarSubordinados()
        {
            Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Parameter.FiltroCodigoOperador req
               = new Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Parameter.FiltroCodigoOperador() { Valor = base.Session.UserId };

            ModelCollection<Operador> operadores = _communicationOperador.ConsultarSubordinados(req);

            foreach (Operador op in operadores)
            {
                if (op.Bloqueado.HasValue && !op.Bloqueado.Value)
                    _operadoresSubordinados.Add(op);
            }

            return _operadoresSubordinados;
        }

        /// <summary>
        /// Verificar o diagrama de sequência ViewSmartClient.Abas.Ordem.Grid.Ordens.
        /// fecha_OrdemAdministradaConcorrente()
        /// </summary>
        /// <param name="request"></param>
        public void FecharOrdemAdministradaConcorrente(Model.Ordem model)
        {
            ChaveOrdem request = null;
            if (model != null)
            {
                request = new ChaveOrdem();
                request.DataOrdem = model.DataOrdem;
                request.NumeroOrdem = model.NumeroOrdem.Value;
                request.NumeroOrdemSubSequencia = model.NumeroOrdemSubSequencia.Value;
            }

            //Verifico se o movimento não está aberto
            this._informacoesMovimento = this.ObterInformacoesMovimento();
            if (this._informacoesMovimento.EstadoMovimento != Model.Enum.TipoMovimento.Abertura)
            {
                //Movimento não está aberto, informo cliente
                View.InformarMovimentoFechado();
            }
            else
            {
                //Confirmo o fechamento da ordem
                if (View.ConfirmarFechamentoOrdemAdmConcorrente())
                {
                    this._communicationManutencaoOrdens.FecharOrdemAdministradaConcorrente(request);
                    View.InformarSucessoFecharOrdemAdmConcorrente();
                }
            }
        }

        /// <summary>
        /// Identifica as propriedades que possuem valores iguais na coleção de ordens
        /// e as alimenta na OrdemAtual
        /// </summary>
        /// <param name="ordens"></param>
        private void IdentificarPropriedadesIguais(ModelCollection<Model.Ordem> ordens)
        {
            System.Reflection.PropertyInfo info = null;
            object valor = null;
            object valor2 = null;
            string chave = null;
            Type tipo = typeof(Model.Ordem);

            //Instancia uma nova OrdemAtual que será o "resumo" das ordens selecionadas
            _ordemAtual = new Model.Ordem();

            //Restaura os valores do dicionário para a validação
            for (int i = 0; i < _dicionarioValidadorPropriedadesOrdem.Keys.Count; i++)
                _dicionarioValidadorPropriedadesOrdem[_dicionarioValidadorPropriedadesOrdem.Keys.ElementAt(i)] = true;

            //Validação
            for (int i = 0; i < ordens.Count; i++)
            {
                for (int countKey = 0; countKey < _dicionarioValidadorPropriedadesOrdem.Keys.Count; countKey++)
                {
                    chave = _dicionarioValidadorPropriedadesOrdem.Keys.ElementAt(countKey);

                    if (_dicionarioValidadorPropriedadesOrdem[chave])
                    {
                        info = tipo.GetProperty(chave);
                        valor = info.GetValue(ordens[i], null);

                        //Inicializa a variável j do for com i + 1
                        //para que as models já validadas não entrem novamente
                        //no laço de repetição
                        for (int j = i + 1; j < ordens.Count; j++)
                        {
                            valor2 = info.GetValue(ordens[j], null);

                            if(valor != null
                                || valor2 != null)
                            {
                                if ((valor == null && valor2 !=null)
                                    || (valor != null && valor2 == null)
                                    || !valor.Equals(valor2))
                                {
                                    _dicionarioValidadorPropriedadesOrdem[chave] = false;
                                    break;
                                }
                            }
                        }

                        //Se o valor for comum a todas models selecionadas no grid,
                        //atribui o valor na OrdemAtual, senão atribui nulo
                        if (_dicionarioValidadorPropriedadesOrdem[chave] == true)
                        {
                            info.SetValue(_ordemAtual, valor, null);
                        }
                        else
                        {
                            info.SetValue(_ordemAtual, null, null);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Verificar o diagrama de atividade ManutencaoOrdens.IncluirDetalheOrdem()
        /// </summary>
        /// <param name="detalheOrdem"></param>
        private void IncluirDetalheOrdem(Model.DetalheOrdem detalheOrdem, Model.Ordem ordem)
        {
            if (detalheOrdem != null)
            {
                try
                {
                    _communicationManutencaoOrdens.IncluirDetalheOrdem(detalheOrdem);

                    ordem.Detalhes.Save(detalheOrdem);
                }
                catch (Exception ex)
                {
                    detalheOrdem.AddError(ex);
                }
            }
        }

        /// <summary>
        /// Inclui uma justificativa para a Ordem
        /// </summary>
        /// <param name="ordem"></param>
        public void IncluirJustificativa(Model.Ordem ordem)
        {
            bool incluirJustificativa = false;
            Model.Justificativa justificativa;

            if (ordem.Justificativas == null)
            {
                ordem.Justificativas = new ModelCollection<Model.Justificativa>();
                ordem.Justificativas.EnableStateControl = true;

                incluirJustificativa = true;
            }
            else if (ordem.Justificativas.GetInserted().Count == 0)
            {
                incluirJustificativa = true;
            }

            if (incluirJustificativa)
            {
                justificativa = new Model.Justificativa();

                justificativa.ApelidoCliente = ordem.ApelidoCliente;
                justificativa.Ativo = ordem.Ativo;
                justificativa.CodigoUsuario = ordem.CodigoUsuario;
                justificativa.DataOrdem = ordem.DataOrdem;

                if (ordem.DataHoraOrdem.HasValue)
                    justificativa.DataHoraOrdem = ordem.DataHoraOrdem.Value;

                if (ordem.NaturezaOperacao != null)
                    justificativa.NaturezaOperacao = ordem.NaturezaOperacao.Value;

                if (ordem.NumeroOrdem.HasValue)
                    justificativa.NumeroOrdem = ordem.NumeroOrdem.Value;

                if (ordem.NumeroOrdemSubSequencia.HasValue)
                    justificativa.NumeroSubSequenciaOrdem = ordem.NumeroOrdemSubSequencia.Value;

                ordem.Justificativas.Add(justificativa);
            }
        }

        /// <summary>
        /// Verificar o diagrama de atividade ManutencaoOrdens.IncluirOrdem()
        /// </summary>
        /// <param name="ordem"></param>
        public void IncluirOrdem(ref Model.Ordem ordem)
        {
            ModelCollection<DetalheOrdem> detalhes = null;
            Model.ChaveOrdem chaveOrdem = null;
            ordem.ClearErrors();

            try
            {
                //Incluir Ordem
                chaveOrdem = _communicationManutencaoOrdens.IncluirOrdem(ordem);

                _ordens.Save(ordem);

                //Armazenar o número gerado para a ordem
                ordem.NumeroOrdem = chaveOrdem.NumeroOrdem;
                ordem.NumeroOrdemSubSequencia = chaveOrdem.NumeroOrdemSubSequencia;
                ordem.DataOrdem = chaveOrdem.DataOrdem;

                Model.Ordem ordemAtualizada = this._communicationManutencaoOrdens.ObterOrdem(chaveOrdem);
                ordemAtualizada.NomeBolsa = this._bolsas.FirstOrDefault(x => x.Codigo == ordemAtualizada.CodigoBolsa).Descricao;

                if (ordem.Detalhes != null)
                    ordemAtualizada.Detalhes = new ModelCollection<DetalheOrdem>(ordem.Detalhes, true);
                
                this._ordens[this._ordens.IndexOf(ordem)] = ordemAtualizada;
                this._ordens.Save(ordemAtualizada);

                //Ordem é do tipo Financiamento ou POP?
                if (ordem.TipoOrdem.Value == Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Enum.TipoOrdem.Financiamento ||
                    ordem.CodigoISIN.Substring(6, 2) == "PP")
                {
                    //Recuperar os detalhes da ordem a serem incluidos
                    detalhes = ordem.Detalhes.GetInserted();

                    //Existem detalhes a serem incluídos?
                    foreach (DetalheOrdem detalhe in detalhes)
                    {
                        //Incluir Detalhe da Ordem                        
                        detalhe.NumeroOrdem = ordem.NumeroOrdem;
                        detalhe.NumeroOrdemSubSequencia = ordem.NumeroOrdemSubSequencia;
                        this.IncluirDetalheOrdem(detalhe, ordem);

                        if (ordem.CasarDetalhes)
                        {
                            CasarDetalhesOrdem(detalhe);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                ordem.AddError(ex);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public void Inicializar()
        {
            if (!this.VerificarAcessoOperador())
            {
                base.View.ProibirAcesso();
            }
            else
            {
                _informacoesMovimento = this.ObterInformacoesMovimento();
                this.ObterPermissoes();
                this.ObterPreferenciasOperador();

                _calendarioFiltro = this.ConsultarCalendario();

                base.View.AtualizarCalendario();

                _operadoresSubordinados = this.ConsultarSubordinados();
                this.OperadoresSubordinadosGrid = (ModelCollection<Model.Operador>)Infra.Common.Serialization.CloneHelper.Clone(_operadoresSubordinados);

                base.View.AtualizarOperadores();

                _bolsas = this.ConsultarBolsas();

                this.ObterParametro();
                //this.ConfigurarParametros();

                _justificativasHistorico = new ModelCollection<Justificativa>();
                _justificativasHistorico.EnableStateControl = true;

                _justificativasRecente = new ModelCollection<Justificativa>();
                _justificativasRecente.EnableStateControl = true;

                _mensagensJustificativas = this.ConsultarMensagens();
                _mensagensObservacoes = new ModelCollection<Mensagem>(_mensagensJustificativas);

                View.AtualizarMensagens();

                CarregarTipoMercado();
                CarregarTipoOrdem();
                CarregarTiposSituacao();
                CarregarTiposLiquidacao();
                CarregarNaturezaOperacao();

                CarregarDicionarioValidador();
            }
        }

        /// <summary>
        /// Obtém o cliente à partir do apelido
        /// </summary>
        /// <param name="apelido"></param>
        /// <returns></returns>
        public bool ObterCliente(string apelido)
        {
            if (!String.IsNullOrEmpty(apelido))
            {
                Model.Parameter.FiltroCliente req = new Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Parameter.FiltroCliente() { Apelido = apelido, UtilizaCache = true };
                _clienteAtual = _communicationCliente.ObterCliente(req);

                if (_clienteAtual != null && _clienteAtual.Situacao == Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Enum.TipoSituacao.Ativo)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// Obtém o cliente á partir do código
        /// </summary>
        /// <param name="codigoCliente"></param>
        /// <returns></returns>
        public bool ObterCliente(int? codigoCliente)
        {
            if (codigoCliente.HasValue)
            {
                Model.Parameter.FiltroCliente req = new Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Parameter.FiltroCliente() { CodigoCliente = codigoCliente, UtilizaCache = true };
                _clienteAtual = _communicationCliente.ObterCliente(req);

                if (_clienteAtual != null && _clienteAtual.Situacao == Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Enum.TipoSituacao.Ativo)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// Verifica se o dígito verificador informado é válido para o cliente
        /// </summary>
        /// <param name="digito"></param>
        /// <returns></returns>
        public Boolean ValidarDigitoVerificador(Int32 digito)
        {
            if (this._clienteAtual != null)
                return this._clienteAtual.Digito == digito;

            return true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private Model.InformacoesMovimento ObterInformacoesMovimento()
        {
            return _communicationControleMovimentoOrdens.ObterInformacoesMovimento(new DataMovimento());
        }

        /// <summary>
        /// Chamar o método <font color="#0000ff">_communicationParametro</font>.
        /// ObterParametro(), atribuir o retorno ao atributo _parametros
        /// </summary>
        private void ObterParametro()
        {
            _parametros = _communicationParametro.ObterParametro();
        }

        /// <summary>
        /// Armazenar no atributo _permissoes e armazenar os seguintes valores nas
        /// propriedades:
        /// - PermiteCancelar = permissão de acesso a função <b>EORD</b>
        /// - PermiteIncluir = permissão de acesso a função <b>IORD</b>
        /// - PermiteAlterar = permissão de acesso a função <b>AORD</b>
        /// </summary>
        private void ObterPermissoes()
        {
            AuthorizationManager autManager = AuthorizationManager.GetInstance();

            _permissoes = new Permissoes();

            _permissoes.PermiteCancelar = autManager.CheckUserAccess("ORD", "EORD");
            _permissoes.PermiteIncluir = autManager.CheckUserAccess("ORD", "IORD");
            _permissoes.PermiteAlterar = autManager.CheckUserAccess("ORD", "AORD");
            _permissoes.PermiteAlterarPercentualCorretagem = autManager.CheckUserAccess("ORD", "ARED");
            _permissoes.PermiteAlterarQuantidade = autManager.CheckUserAccess("ORD", "AQTD");
            _permissoes.PermiteAlterarAtivo = autManager.CheckUserAccess("ORD", "APAP");
            _permissoes.PermiteAlterarCliente = autManager.CheckUserAccess("ORD", "ACLI");

            View.HabilitarAlteracaoPercentualCorretagem(_permissoes.PermiteAlterarPercentualCorretagem);
            View.HabilitarAlteracaoQuantidade(_permissoes.PermiteAlterarQuantidade);
            View.HabilitarAlteracaoAtivo(_permissoes.PermiteAlterarAtivo);
            View.HabilitarAlteracaoCliente(_permissoes.PermiteAlterarCliente);
        }

        /// <summary>
        /// Chamar o método <font color="#0000ff">_communicationOperador</font>.
        /// ObterPreferencias() e armazenar o retorno no atributo _preferencias
        /// </summary>
        private void ObterPreferenciasOperador()
        {
            _preferencias = _communicationOperador.ObterPreferencias(base.Session.UserId);
        }

        /// <summary>
        /// Obter Saldo Negociavel
        /// </summary>
        /// <param name="ordem"></param>
        public void ObterSaldoNegociavel(Model.Ordem ordem, Model.Enum.NaturezaOperacao? naturezaOperacao)
        {
            Model.Saldo saldo = null;
            
            if ((new Sinacor.UI.Bovespa.ManutencaoOrdens.Communication.Acesso(this.Session)).VerificarSistemaInstalado("CF") &&
                this._parametros.SaldoNegociavelCustodia &&
                (ordem.NaturezaOperacao != null && ordem.NaturezaOperacao.Value == naturezaOperacao ||
                naturezaOperacao == null))
            {
                try
                {
                    saldo =  this._communicationManutencaoOrdens.ObterSaldoNegociavel(new DadosSaldoNegociavel
                    {
                        Ativo = ordem.Ativo,
                        Cliente = ordem.CodigoCliente.Value,
                        Mercado = (Model.Enum.TipoMercado?)ordem.Mercado,
                        Quantidade = ordem.Quantidade
                    });

                    View.ApresentarSaldoNegociavel(saldo.Valor, ordem);
                }
                catch (Exception ex)
                {
                    this.HandleException(ex, ErrorLevel.Critical);
                }
            }
        }

        /// <summary>
        /// Verificar o diagrama de atividade ManutencaoOrdens.ObterTitulo()
        /// </summary>
        /// <param name="ativo"></param>
        public bool ObterTitulo(string ativo)
        {
            if (!String.IsNullOrEmpty(ativo))
            {
                Model.Parameter.FiltroTitulo req = new Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Parameter.FiltroTitulo() { CodigoNegocio = ativo, DataPregao = FiltroOrdens.DataPregao.Value, UtilizaCache = true };
                _tituloAtual = _communicationTitulo.ObterTitulo(req);

                if (_tituloAtual != null)
                {
                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// Salvar
        /// </summary>
        public bool Salvar()
        {
            bool errosOrdem = false;
            Model.Ordem ordem;
            ModelCollection<Model.Ordem> ordensModificadas;

            //Verifica se o movimento está aberto
            if (_informacoesMovimento.EstadoMovimento == Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Enum.TipoMovimento.Abertura)
            {
                ordensModificadas = _ordens.GetChanged();

                for (int i = 0; i < ordensModificadas.Count; i++)
                {
                    ordem = ordensModificadas[i];

                    switch (ordem.State)
                    {
                        case State.Deleted:
                            CancelarOrdem(ref ordem);
                            break;
                        case State.Inserted:
                            IncluirOrdem(ref ordem);
                            break;
                        case State.Updated:
                            AlterarOrdem(ref ordem);
                            break;
                    }

                    if (!errosOrdem
                        && ordem.HasErrors)
                    {
                        errosOrdem = true;
                    }
                    else
                    {
                        //Anula as justificativas para que
                        //elas sejam populadas com os dados atualizados na próxima chamada à aba de Justificativas
                        ordem.Justificativas = null;

                        //Define como false para permitir que futuras consultas às justificativas
                        ordem.CacheJustificativasConsultadas = false;
                    }
                }
                
                if (!errosOrdem)
                    this.View.InformarOperacaoRealizadaSucesso();

            }
            else
            {
                //Informa ao usuário que o movimento está fechado
                View.InformarMovimentoFechado();
            }

            return errosOrdem;
        }

        /// <summary>
        /// <b>Descrição:</b> Verifica se o usuário que está acessando a tela é operador
        /// 
        /// Consumir o método <font color="#0000ff">_communicationOperador</font>.
        /// <b>ConsultarOperadores()</b>, passando como parâmetro de entrada um objeto do
        /// tipo Model.Parameter.FiltroOperador com a propriedade CodigoOperador preenchida
        /// com o valor de base.Session.UserId
        /// 
        /// <b>Se</b> retorno igual a nulo ou quantidade igual a zero
        ///    retornar falso
        /// <b>Senão
        /// </b>   retornar verdadeiro
        /// <b>Fim Se
        /// </b>
        /// </summary>
        private bool VerificarAcessoOperador()
        {
            Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Parameter.FiltroOperador req
                = new Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Parameter.FiltroOperador() { CodigoOperador = base.Session.UserId };
            ModelCollection<Operador> operadores = _communicationOperador.ConsultarOperadores(req);

            return !(operadores == null || operadores.Count == 0);
        }

        /// <summary>
        /// Verificar o diagrama de atividade ManutencaoOrdens.VerificarEstadoDetalheOrdem()
        /// Obs:. Este método deverá ser chamado no evento ApplyingStyle do SinacorDataGrid de Detalhe Ordem.
        /// </summary>
        /// <param name="request"></param>
        public void VerificarEstadoDetalheOrdem(Model.DetalheOrdem request)
        {
            if (request.QuantidadeExecutada == 0)
            {
                View.ApresentarDetalheOrdemNaoCasado();
            }
            else if (request.QuantidadeExecutada == request.Quantidade)
            {
                View.ApresentarDetalheOrdemCasado();
            }
            else if (request.QuantidadeExecutada > 0 
                     && request.QuantidadeExecutada < request.Quantidade)
            {
                View.ApresentarDetalheOrdemParcialmenteCasado();
            }
        }

        /// <summary>
        /// Verificar o diagrama de atividade ManutencaoOrdens.VerificarEstadoOrdem()
        /// Obs:. Este método deverá ser chamado no evento ApplyingStyle do SinacorDataGrid
        /// de Ordem.
        /// </summary>
        /// <param name="request"></param>
        public void VerificarEstadoOrdem(Model.Ordem request)
        {
            if (request.Situacao == Sinacor.UI.Bovespa.ManutencaoOrdens.Model.Enum.SituacaoOrdem.Cancelada)
            {
                //Cinza
                base.View.ApresentarOrdemCancelada();
            }
            else
                if (request.QuantidadeExecutada == 0)
                {
                    if (request.PossuiPreBoleto)
                    {
                        //Magenta
                        View.ApresentarOrdemNaoCasadaComPreBoleto();
                    }
                    else
                    {
                        //Vermelha
                        base.View.ApresentarOrdemNaoCasada();
                    }
                }
                else
                    if (request.QuantidadeExecutada == request.Quantidade)
                    {
                        //Azul
                        base.View.ApresentarOrdemCasada();
                    }
                    else
                        if ((request.QuantidadeExecutada > 0) && (request.QuantidadeExecutada < request.Quantidade))
                        {
                            //Verde
                            base.View.ApresentarOrdemParcialmenteCasada();
                        }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="numeroOrdem"></param>
        /// <returns></returns>
        public bool VerificarExistenciaOrdem(int numeroOrdem)
        {
            ChaveOrdem req = new ChaveOrdem() { NumeroOrdem = numeroOrdem, DataOrdem = FiltroOrdens.DataPregao.Value };

            return _communicationManutencaoOrdens.VerificarExistenciaOrdem(req);
        }

        /// <summary>
        /// Configura a tela para inicializar a inclusão ou alteração de uma única ordem
        /// Utilizando tanto para modo formulário quanto no modo grid
        /// </summary>
        public void ConfigurarManutencaoUnitaria()
        {
            // Verifica se o dígito verificador é obrigatório
            VerificarDigitoVerificadorObrigatorio();

            _tituloAtual = null;
            _clienteAtual = null;
            _emissores = new ModelCollection<Emissor>();

            View.AtribuirSitucaoObrigatorio(_estado == Model.Enum.EstadoTela.Alteracao);
            View.HabilitarAlteracaoSituacao(_estado == Model.Enum.EstadoTela.Alteracao);

            if (_estado == Model.Enum.EstadoTela.Inclusao)
            {
                // Atribuir para a data da ordem a data do movimento
                _ordemAtual.DataOrdem = _informacoesMovimento.DataMovimento;
                _ordemAtual.DataHoraOrdem = _informacoesMovimento.DataMovimento;

                //Atribuir 0 ao numero ordem subsequencia
                _ordemAtual.NumeroOrdemSubSequencia = 0;

                if (_preferencias != null)
                {
                    _ordemAtual.CodigoOperador = _preferencias.CodigoOperador;
                    _ordemAtual.CodigoBolsa = _preferencias.Bolsa;
                    _ordemAtual.Mercado = _preferencias.Mercado;
                    _ordemAtual.TipoOrdem = _preferencias.Ordem;
                }

                _ordemAtual.TipoLiquidacao = Model.Enum.TipoLiquidacao.Normal;

                _ordemAtual.ValorOrdem = new ValorOrdem();
                _ordemAtual.ValorOrdem.ValorExecutado = 0;
                _ordemAtual.ValorOrdem.ValorNaoExecutado = 0;
                _ordemAtual.ValorOrdem.ValorTotal = 0;

                _ordemAtual.Discricionaria = false;
                _ordemAtual.IndicadorClientePessoaVinculada = false;
                _ordemAtual.IndicadorDesprezaSaldo = false;
                _ordemAtual.IndicadorOrdemAdmConcorrente = false;

                _ordemAtual.Situacao = Model.Enum.SituacaoOrdem.Demais;
            }
            else
            {
                //Inicia o campo Situação caso o campo esteja nulo
                if (_ordemAtual != null
                    && _ordemAtual.Situacao == null)
                {
                    _ordemAtual.Situacao = new EnumWrapper<Model.Enum.SituacaoOrdem>(Model.Enum.SituacaoOrdem.AbertaViaSinalNegocio);
                }

                ConfigurarOrdemDistribuida(_ordemAtual);

                ObterTitulo(_ordemAtual.Ativo);
                ConfigurarTitulo();

                ObterCliente(_ordemAtual.ApelidoCliente);
                ApresentarCliente();

                CalcularValorOrdem(_ordemAtual);

                if (_ordemAtual.Mercado != null)
                    ConfigurarMercado(_ordemAtual.Mercado.Value);

                if (_ordemAtual.TipoOrdem != null)
                    ConfigurarTipoOrdem(_ordemAtual.TipoOrdem.Value);

                if (_ordemAtual.IndicadorOrdemAdmConcorrente.HasValue
                    && _ordemAtual.IndicadorOrdemAdmConcorrente.Value)
                {
                    View.HabilitarAlteracaoCliente(false);
                    View.HabilitarAlteracaoTipoOrdem(false);
                }
            }

            View.AtribuirFocoCampoCliente();

            if(_modoUtilizado == Model.Enum.ModoTela.Formulario)
                View.AtualizarFormulario();

            View.AtribuirNaturezaOperacao(_ordemAtual.NaturezaOperacao);
        }
        
        /// <summary>
        /// Configura o formulário para alteração em lote de ordens
        /// </summary>
        /// <param name="ordens"></param>
        public void ConfigurarAlteracaoLote(ModelCollection<Model.Ordem> ordens)
        {
            _tituloAtual = null;
            _clienteAtual = null;
            _emissores = new ModelCollection<Emissor>();

            IdentificarPropriedadesIguais(ordens);

            //Se o cliente for o mesmo para as ordens alteradas em lote
            if (_dicionarioValidadorPropriedadesOrdem["CodigoCliente"])
            {
                if (ObterCliente(_ordemAtual.CodigoCliente))
                {
                    this.View.ApresentarNomeCliente(String.Format("{0} {1}", _clienteAtual.Nome, _clienteAtual.ComplementoNome));
                    _ordemAtual.ApelidoCliente = _clienteAtual.Apelido;
                    _ordemAtual.DigitoCliente = (short)_clienteAtual.Digito.Value;
                }
                else
                {
                    this.View.ApresentarNomeCliente(String.Empty);
                    _ordemAtual.ApelidoCliente = String.Empty;
                    _ordemAtual.DigitoCliente = null;
                }
            }

            //Se o ativo for o mesmo para as ordens alteradas em lote
            if (_dicionarioValidadorPropriedadesOrdem["Ativo"])
            {
                if (ObterTitulo(_ordemAtual.Ativo))
                {
                    View.ApresentarDescricaoTitulo(_tituloAtual.Descricao);
                    View.AtribuirCodigoISIN(_tituloAtual.Isin);
                }
                else
                {
                    View.ApresentarDescricaoTitulo(String.Empty);
                    View.AtribuirCodigoISIN(String.Empty);
                }
            }
            
            ConfigurarOrdemDistribuida(_ordemAtual);

            View.AtualizarFormulario();

            //Caso o tipo das ordens que serão alteradas em lote seja único, e seja Financiamento
            //o ativo não será obrigatório pois seu valor sempre será nulo
            //e os campos que são obrigatórios para ordem financiamento deverão ser validados contra
            //o valor do dicionário.
            if (_ordemAtual.TipoOrdem != null
               && _ordemAtual.TipoOrdem.Value == Model.Enum.TipoOrdem.Financiamento)
            {
                View.AtribuirAtivoObrigatorio(false);
                View.AtribuirPercentualFinanciamentoObrigatorio(_dicionarioValidadorPropriedadesOrdem["PercentualFinanciamento"]);
                View.AtribuirValorFinanciamentoObrigatorio(_dicionarioValidadorPropriedadesOrdem["ValorFinanciamento"]);
                View.AtribuirVencimentoTermoObrigatorio(_dicionarioValidadorPropriedadesOrdem["PrazoVencimentoTermo"]);
            }
            else
            {
                View.AtribuirAtivoObrigatorio(_dicionarioValidadorPropriedadesOrdem["Ativo"]);
            }

            View.AtribuirClienteObrigatorio(_dicionarioValidadorPropriedadesOrdem["CodigoCliente"]);
            View.AtribuirQuantidadeObrigatorio(_dicionarioValidadorPropriedadesOrdem["Quantidade"]);
            View.AtribuirSitucaoObrigatorio(_dicionarioValidadorPropriedadesOrdem["Situacao"]);
            View.AtribuirTipoOrdemObrigatorio(_dicionarioValidadorPropriedadesOrdem["TipoOrdem"]);
            View.AtribuirOperadorObrigatorio(_dicionarioValidadorPropriedadesOrdem["CodigoOperador"]);
            View.AtribuirMercadoObrigatorio(_dicionarioValidadorPropriedadesOrdem["Mercado"]);
            View.AtribuirTipoLiquidacaoObrigatorio(_dicionarioValidadorPropriedadesOrdem["TipoLiquidacao"]);
            View.AtribuirPercentualCorretagemObrigatorio(_dicionarioValidadorPropriedadesOrdem["PercentualCorretagem"]);

            View.AtribuirNaturezaOperacao(_ordemAtual.NaturezaOperacao);
        }

        /// <summary>
        /// Configurar Carteira Detalhe Ordem
        /// </summary>
        public Int16? ConfigurarCarteiraDetalheOrdem(Model.DetalheOrdem detalheOrdem)
        {
            if (detalheOrdem.Mercado != null)
            {
                if (detalheOrdem.Mercado.Value == Model.Enum.TipoMercado.Termo
                    && detalheOrdem.NaturezaOperacao != null
                    && detalheOrdem.NaturezaOperacao.Value == Model.Enum.NaturezaOperacao.Venda
                    && !String.IsNullOrEmpty(detalheOrdem.Ativo)
                    && detalheOrdem.Ativo.ToUpper().EndsWith("S"))
                {
                    return 0;
                }
                else if (detalheOrdem.Mercado.Value == Model.Enum.TipoMercado.Vista)
                {
                    if (this._ordemAtual.TipoOrdem.Value == Model.Enum.TipoOrdem.Financiamento)
                    {
                        if (detalheOrdem.NaturezaOperacao != null
                            && detalheOrdem.NaturezaOperacao.Value == Model.Enum.NaturezaOperacao.Compra)
                        {
                            return 268;
                        }
                    }
                    else
                        return 277;
                }
                else if (detalheOrdem.Mercado.Value == Model.Enum.TipoMercado.OpcaoCompra ||
                         detalheOrdem.Mercado.Value == Model.Enum.TipoMercado.OpcaoVenda)
                {
                    return 277;
                }
            }

            return null;
        }

        public bool ValidarOrdemPreBoleto()
        {
            if (_ordemAtual.DataValidade < DateTime.Now)
            {
                if (!AuthorizationManager.GetInstance().CheckUserAccess("ORD", "D1SIM"))
                {
                    View.InformarUsuarioSemPermissaoRetroativa();
                    return false;
                }
            }

            if (_ordemAtual.IndicadorCasaOrdem.HasValue
                && _ordemAtual.IndicadorCasaOrdem.Value)
                return true;
            else
            {
                View.InformarOrdemNaoAceitaCasamento();
                return false;
            }
        }

        private void LimparDetalhes()
        {
            if(this._ordemAtual != null) this._ordemAtual.Detalhes.Clear();
            this.View.AtualizarDetalhesOrdem();
        }

        /// <summary>
        /// Configura os campos que podem ser alterados caso a ordem esteja distribuida;
        /// </summary>
        public void ConfigurarOrdemDistribuida(Model.Ordem ordem)
        {
            if (ordem.Distribuida.HasValue 
                && ordem.Distribuida.Value)
            {
                //Desabilita
                View.HabilitarAlteracaoAtivo(false);
                View.HabilitarAlteracaoBolsa(false);
                View.HabilitarAlteracaoCarteira(false);
                View.HabilitarAlteracaoCliente(false);
                View.HabilitarAlteracaoDiscricionaria(false);
                View.HabilitarAlteracaoIndicadorSistemaExterno(false);
                View.HabilitarAlteracaoMercado(false);
                View.HabilitarAlteracaoNaturezaOperacao(false);
                View.HabilitarAlteracaoPercentualCorretagem(false);
                View.HabilitarAlteracaoPreco(false);
                View.HabilitarAlteracaoQuantidade(false);
                View.HabilitarAlteracaoQuantidadeAnexoIV(false);
                View.HabilitarAlteracaoQuantidadeAnexoV(false);
                View.HabilitarAlteracaoSituacao(false);
                View.HabilitarAlteracaoTipoLiquidacao(false);
                View.HabilitarAlteracaoTipoOrdem(false);
                View.HabilitarAlteracaoValorDolar(false);
                View.HabilitarAlteracaoVencimentoTermo(false);
                View.HabilitarAlteracaoOrdemOriginal(false);
            }
        }

        #endregion Métodos
    }

}
